home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / c / simplecalc / calc.math.c < prev    next >
C/C++ Source or Header  |  2000-02-28  |  9KB  |  343 lines

  1. /* -----------------------------------------------------------
  2.   $VER: calc.math.c 1.01 (22.02.2000)
  3.  
  4.   maths core for calculator project
  5.  
  6.   (C) Copyright 2000 Matthew J Fletcher - All Rights Reserved.
  7.   amimjf@connectfree.co.uk - www.amimjf.connectfree.co.uk
  8.   ------------------------------------------------------------ */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include <dos/dos.h>
  16. #include <exec/types.h>
  17. #include <exec/exec.h>
  18. #include <libraries/gadtools.h>
  19. #include <graphics/gfxmacros.h>
  20. #include <graphics/gfxbase.h>
  21.  
  22. #include <intuition/intuition.h>
  23. #include <intuition/intuitionbase.h>
  24.  
  25. #include <clib/intuition_protos.h>
  26. #include <clib/graphics_protos.h>
  27. #include <clib/exec_protos.h>
  28.  
  29. #include "Calc.h"
  30.  
  31. #define MAX 255 /* max char precision */
  32.  
  33. /* buffers for maths core preserved betwen calls */
  34. long double result=0; /* final total */
  35. char number1[MAX];    /* first number */
  36. char op;              /* math op */
  37. char number2[MAX];    /* second number */
  38. int i=0,y=0;
  39. int flag=0,sflag=0;  /* control flags */
  40.  
  41. /* tape history */
  42. extern int UseTape;
  43. /* maths mode */
  44. extern int mode;
  45. /* whats on screen */
  46. extern char buffer[100];
  47.  
  48. double do_math(char inchar)
  49. { /* maths core for calculator */
  50. char *t1,*t2;
  51. static long double realnumber1,realnumber2,realresult;
  52.  
  53. /* if previous result exists & op is first gad pressed */
  54. if ( ((inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
  55.      (inchar == '*' )) && (result != 0)
  56.    )
  57.    /* second or more calc */
  58.    {
  59.     op = inchar; /* store */
  60.     // printf("operation (%c)\n",op);
  61.     draw_op(op);
  62.     flag =1;  /* now only fill second number */
  63.     sflag =1; /* calc, uses stored number as number1 */
  64.  
  65.     /* copy previous result to number1 store */
  66.     realnumber1 = result;
  67.    }
  68.  
  69. /* if input is number and op is blank store */
  70. if ( ((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==0))
  71.    /* make sure we are first number */
  72.    {
  73.     /* first distroy, old result, cos user did NOT, want */
  74.     /* to perform an operation on it (they started to type */
  75.     /* a new number !!) */
  76.     result=0;
  77.  
  78.     number1[i] = inchar; /* add next input */
  79.     i++;
  80.     // printf("1stored (%c), number1 (%s)\n",inchar, number1);
  81.     clear_display();
  82.     draw_display(number1,NULL);
  83.    }
  84.  
  85. /* if input is number and op is NOT blank store */
  86. if (((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==1))
  87.    /* make sure we are second number */
  88.    {
  89.     number2[y] = inchar; /* add next input */
  90.     y++;
  91.     // printf("2stored (%c), number2 (%s)\n",inchar, number2);
  92.     clear_display();
  93.     draw_display(number2,NULL);
  94.    }
  95.  
  96.  
  97. /* if we get a operations store */
  98. if ( (inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
  99.      (inchar == '*' ) || (inchar == '(' ) || (inchar == ')' ) ||
  100.      (inchar == '<' ) && (sflag == 0) /* skip if op allready parsed */
  101.    ) /* its an operation */
  102.  
  103.    {
  104.     op = inchar; /* store */
  105.     // printf("operation (%c)\n",op);
  106.     clear_display();
  107.     draw_op(op);
  108.     draw_display(NULL,NULL); /* a refresh basicly */
  109.     flag =1; /* now only fill second number */
  110.    }
  111.  
  112.  
  113. /* if = pressed */
  114. if (inchar == '=')
  115.     {
  116.     /* we work out result imedieatly */
  117.  
  118.     /* convert to numbers */
  119.     if (sflag ==0) realnumber1 = strtod(number1, &t1);
  120.     /* or not if one is available */
  121.     if (sflag ==1) realnumber1 = result;
  122.  
  123.     realnumber2 = strtod(number2, &t2);
  124.     /* second number always input */
  125.  
  126.     if (UseTape ==1)
  127.         printf("%Lg %c %Lg\n ",realnumber1,op,realnumber2);
  128.  
  129.     switch (op)
  130.     {
  131.     case '+':
  132.     realresult = (realnumber1 + realnumber2);
  133.     break;
  134.  
  135.     case '-':
  136.     realresult = (realnumber1 - realnumber2);
  137.     break;
  138.  
  139.     case '/':
  140.     realresult = (realnumber1 / realnumber2);
  141.     break;
  142.  
  143.     case '*':
  144.     realresult = (realnumber1 * realnumber2);
  145.     break;
  146.  
  147.     default:
  148.     printf("Something broke, couldent get operand ! got (%c)\n",op);
  149.     break;
  150.     };
  151.  
  152.     /* copy to store */
  153.     result = realresult;
  154.  
  155.     /* output conversion depends on mode selected */
  156.     /* ALL maths done internally as decimal */
  157.  
  158.     switch (mode)
  159.     {
  160.     case 0: /* DEC */
  161.     /* copy data for display */
  162.     sprintf(buffer, "%Ld",realresult);
  163.     /* tape display */
  164.     if (UseTape ==1)
  165.         printf("=%s %Ld%s\n",BOLD,realresult,NORMAL);
  166.     break;
  167.     case 1: /* FLT */
  168.     sprintf(buffer, "%Lg",realresult);
  169.     if (UseTape ==1)
  170.         printf("=%s %Lg%s\n",BOLD,realresult,NORMAL);
  171.     break;
  172.     case 2: /* HEX */
  173.     sprintf(buffer, "%Lx",realresult);
  174.     if (UseTape ==1)
  175.         printf("=%s %Lx%s\n",BOLD,realresult,NORMAL);
  176.     break;
  177.     case 3: /* OCT */
  178.     sprintf(buffer, "%Lo",realresult);
  179.     if (UseTape ==1)
  180.         printf("=%s %Lo%s\n",BOLD,realresult,NORMAL);
  181.     break;
  182.     case 4: /* BIN */
  183.     sprintf(buffer, "%Ld",realresult);
  184.     /* display return from atob (int) */
  185.     if (UseTape ==1)
  186.         printf("=%s %Ld%s\n",BOLD,atob(buffer),NORMAL);
  187.     break;
  188.     case 5: /* EXPO */
  189.     sprintf(buffer, "%Le",realresult);
  190.     if (UseTape ==1)
  191.         printf("=%s %.Le%s\n",BOLD,realresult,NORMAL);
  192.     break;
  193.     };
  194.  
  195.     /* check for overload */
  196.     if (stricmp(buffer,"NaN")==0)
  197.         strcpy(buffer,"Overload !!");
  198.  
  199.     /* clean our mess */
  200.     clear_buffers();
  201.     clear_display();
  202.     draw_display(buffer,NULL);
  203.     /* we are safe to call again now */
  204.  
  205.     } /* end calculation */
  206.  
  207.  
  208. } /* end do_math */
  209.  
  210.  
  211. int draw_display(char *inchar, int mode)
  212. { /* re-draw display */
  213. static int smode;
  214.  
  215.     /* store untill, user changes */
  216.     if (mode != NULL)
  217.     smode = mode;
  218.     /* NULL for no change */
  219.  
  220.     /* print maths mode */
  221.     switch (smode)
  222.     {
  223.     case 0: /* DEC */
  224.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  225.                       GTTX_Text, (STRPTR)"DEC", TAG_END);
  226.     break;
  227.     case 1: /* FLT */
  228.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  229.                       GTTX_Text, (STRPTR)"FLT", TAG_END);
  230.     break;
  231.     case 2: /* HEX */
  232.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  233.                       GTTX_Text, (STRPTR)"HEX", TAG_END);
  234.     break;
  235.     case 3: /* OCT */
  236.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  237.                       GTTX_Text, (STRPTR)"OCT", TAG_END);
  238.     break;
  239.     case 4: /* BIN */
  240.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  241.                       GTTX_Text, (STRPTR)"BIN", TAG_END);
  242.     break;
  243.     case 5: /* EXPO */
  244.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  245.                       GTTX_Text, (STRPTR)"EXPO", TAG_END);
  246.     break;
  247.     };
  248.  
  249.     /* print display */
  250.     if (inchar != NULL)
  251.     GT_SetGadgetAttrs(CalcGadgets[24], CalcWnd, NULL,
  252.                       GTTX_Text, (STRPTR)inchar, TAG_END);
  253.  
  254.     /* NULL passed, if no change required */
  255.     /* note we dont buffer the display buffer!! */
  256.     /* so it needs to be re-passed, if you want */
  257.     /* a display and/or an update */
  258.  
  259. }  /* end draw_display */
  260.  
  261.  
  262. void clear_display(void)
  263. {
  264. /* just draw a filed rectangle over display */
  265. /* re-calc each time for font size change */
  266. BYTE BorderLeft = CalcWnd->BorderLeft;
  267. BYTE BorderTop = CalcWnd->BorderTop;
  268. BYTE BorderRight = CalcWnd->BorderRight;
  269. BYTE BorderBottom = CalcWnd->BorderBottom;
  270.  
  271.     //SetAPen(CalcWnd->RPort,4); /* dark grey */
  272.     //RectFill(CalcWnd->RPort,11,13,210,27);
  273.  
  274.     GT_SetGadgetAttrs(CalcGadgets[24], CalcWnd, NULL,
  275.                       GTTX_Text, (STRPTR)" ", TAG_END);
  276.     GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
  277.                       GTTX_Text, (STRPTR)" ", TAG_END);
  278.  
  279. } /* end clear display */
  280.  
  281.  
  282. void clear_buffers(void)
  283. {
  284. int x=0;
  285. /* if erase selected or CA, we flush all internal */
  286. /* data stores, so we can start again */
  287.  
  288.     i=0,y=0;
  289.     flag=0;  /* pointers */
  290.     sflag=0;
  291.  
  292.     for (x=0; x != MAX; x++) /* stores */
  293.         { number1[x] =0;
  294.           number2[x] =0;
  295.         }
  296.     /* we are safe to call again now */
  297.  
  298. } /* end clear buffers */
  299.  
  300.  
  301. void draw_op(char op)
  302. { /* place operation on display */
  303.  
  304.     switch (op)
  305.     { /* print op type */
  306.     case '+':
  307.     GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
  308.                       GTTX_Text, (STRPTR)"+", TAG_END);
  309.     break;
  310.     case '-':
  311.     GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
  312.                       GTTX_Text, (STRPTR)"-", TAG_END);
  313.     break;
  314.     case '/':
  315.     GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
  316.                       GTTX_Text, (STRPTR)"/", TAG_END);
  317.     break;
  318.     case '*':
  319.     GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
  320.                       GTTX_Text, (STRPTR)"*", TAG_END);
  321.     break;
  322.     };
  323.  
  324. } /* end print op */
  325.  
  326.  
  327. int atob(char *str)
  328. /* ASCII-to-binary conversion */
  329. {
  330. int val;
  331.  
  332.     for (val = 0; *str; str++)
  333.     {
  334.     val *= 2;
  335.  
  336.     if (*str == '1')
  337.         val++;
  338.         else if (*str != '0')
  339.         return(-1);
  340.     }
  341.     return(val);
  342. }
  343.